import 'dart:convert';
import 'dart:io';

import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:maiji_flutter_common/account/maiji_common_account.dart';
import 'package:maiji_flutter_common/network/error/maiji_flutter_http_error.dart';

import 'maiji_flutter_http.dart';

enum HttpDataSource { java, go }

enum HttpMethod {
  get("GET"),
  post("POST"),
  put("PUT");

  final String value;

  const HttpMethod(this.value);
}

class HttpEnvManager {
  static const String _baseUrl = "https://api.maijitv.com";
  static const String _baseUrlUat = "http://menguat.maijimaiji.cn";

  static const String _baseGoUrl = "https://api02.maijitv.com";
  static const String _baseGoUrlUat = "https://dev-api02.maijitv.com";

  static String getBaseUrl({dataSource = HttpDataSource.java}) {
    if (dataSource == HttpDataSource.go) {
      return const bool.fromEnvironment('dart.vm.product', defaultValue: true)
          ? _baseGoUrl
          : _baseGoUrlUat;
    } else {
      return const bool.fromEnvironment('dart.vm.product', defaultValue: true)
          ? _baseUrl
          : _baseUrlUat;
    }
  }

  static String getUrlByPath(String path, {dataSource = HttpDataSource.java}) {
    String baseUrl = getBaseUrl(dataSource: dataSource);
    if (path.startsWith("/")) {
      return baseUrl + path;
    }
    return "$baseUrl/$path";
  }
}

class HttpResult {
  HttpResult({
    dynamic body,
    String? msgCd,
    String? msgInfo,
  }) {
    _body = body;
    _msgCd = msgCd;
    _msgInfo = msgInfo;
  }

  HttpResult.fromJson(dynamic json) {
    _body = json['body'];
    _msgCd = json['msgCd'];
    _msgInfo = json['msgInfo'];
  }

  dynamic _body;
  String? _msgCd;
  String? _msgInfo;

  HttpResult copyWith({
    dynamic body,
    String? msgCd,
    String? msgInfo,
  }) =>
      HttpResult(
        body: body ?? _body,
        msgCd: msgCd ?? _msgCd,
        msgInfo: msgInfo ?? _msgInfo,
      );

  dynamic get body => _body;

  String? get msgCd => _msgCd;

  String? get msgInfo => _msgInfo;

  Map<String, dynamic> toJson() {
    final map = <String, dynamic>{};
    map['body'] = _body;
    map['msgCd'] = _msgCd;
    map['msgInfo'] = _msgInfo;
    return map;
  }
}

class NetworkClient {
  static const _signSecretKey = "K3048b2xVAY6j0eV";

  static final NetworkClient _instance = NetworkClient._internal();

  factory NetworkClient.instance() {
    return _instance;
  }

  NetworkClient._internal() {
    dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {
      String sign = options.queryParameters.toString() + _signSecretKey;
      options.headers["sign"] = md5.convert(utf8.encode(sign));
      options.headers["token"] = UserManager.instance.token;
      options.headers["appOs"] = Platform.operatingSystem;
      options.headers["appName"] = "com.maijitv.app.flutter";
      return handler.next(options);
    }));
    // 日志拦截器，添加到队尾
    dio.interceptors
        .add(LogInterceptor(requestBody: kDebugMode, responseBody: kDebugMode));
  }

  Future<dynamic> get(String path,
      {HttpDataSource? dataSource,
      Map<String, dynamic>? headers,
      Map<String, dynamic>? params}) async {
    return request(path, HttpMethod.get, dataSource,
        headers: headers, params: params);
  }

  Future<dynamic> post(String path,
      {HttpDataSource? dataSource,
      Map<String, dynamic>? headers,
      Map<String, dynamic>? params}) async {
    return request(path, HttpMethod.post, dataSource,
        headers: headers, params: params);
  }

  Future<dynamic> put(String path,
      {HttpDataSource? dataSource,
      Map<String, dynamic>? headers,
      Map<String, dynamic>? params}) async {
    return request(path, HttpMethod.put, dataSource,
        headers: headers, params: params);
  }

  Future<dynamic> request<T>(
      String path, HttpMethod method, HttpDataSource? dataSource,
      {Map<String, dynamic>? headers,
      Map<String, dynamic>? params,
      Options? options}) async {
    options ??= Options(method: method.value, headers: headers);
    dataSource ??= HttpDataSource.java;
    String url = HttpEnvManager.getUrlByPath(path, dataSource: dataSource);
    Response<dynamic> response =
        await dio.request(url, data: jsonEncode(params), options: options);
    if (dataSource == HttpDataSource.java) {
      HttpResult result = HttpResult.fromJson(response.data);
      // 处理业务逻辑
      if (result._msgCd?.endsWith("00000") == true) {
        // 成功
        return Future(() => result.body);
      }
      if (result._msgCd == "ACS00002") {
        // Token 过期
        UserManager.instance.loginOut();
      }
      throw Future.error(
          NetworkException(msgCd: result._msgCd, msgInfo: result._msgInfo));
    } else if (dataSource == HttpDataSource.go) {
      return Future(() => response.data);
    } else {
      if (response.statusCode == 200) {
        return Future(() => response.data);
      }
      throw Future.error(Exception(response.statusMessage));
    }
  }
}
